package com.example.discard;

import com.example.Constant;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * @author zhanghui
 * @date 2021/12/6 11:23
 */
public class DiscardServer {
    public static void main(String[] args) throws IOException {
        startServer();
    }

    public static void startServer() throws IOException {
        // 获取selector选择器
        Selector selector = Selector.open();
        // 获取服务端通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 配置通道为非阻塞并绑定端口
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(Constant.SERVER_PORT));
        // 将通道注册到服务器并监听事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务器启动成功");

        // 轮询事件 select()为阻塞方法, 有事件发送时才返回, 也可以指定一定时间内必须返回
        while (selector.select() > 0) {
            Iterator<SelectionKey> selectKeys = selector.selectedKeys().iterator();
            while (selectKeys.hasNext()) {
                // 获取当前key
                SelectionKey selectionKey = selectKeys.next();
                // 根据事件类型做相应处理

                if (selectionKey.isAcceptable()) {
                    // 若是连接事件, 则通过serverSocketChannel获取新的通道并注册
                    SocketChannel newSocketChannel = serverSocketChannel.accept();
                    newSocketChannel.configureBlocking(false);
                    newSocketChannel.register(selector, SelectionKey.OP_READ);
                    System.out.println("客户端[" + newSocketChannel.getRemoteAddress() + "]已连接");
                } else if (selectionKey.isReadable()) {
                    // 若是可读事件, 则通过key获取通道, 并从通道读取数据
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int readLength = 0;
                    while ((readLength = socketChannel.read(buffer)) > 0) {
                        buffer.flip();
                        System.out.print("[" + socketChannel.getRemoteAddress() + "]: " + new String(buffer.array(), 0, readLength));
                        System.out.println();
                        buffer.clear();
                    }
//                    socketChannel.close();
                }

                // 移出选择键
                selectKeys.remove();
            }
        }
    }
}
